#include"stdafx.h"
#include "AddProcess.h"

AddProcess::AddProcess(string command,allTaskList *givenLists,allCommandStack *givenStacks):LogicProcess(command,givenLists,givenStacks){

	startKeyWord.push_back("from");
	endKeyWord.push_back("before");
	endKeyWord.push_back("at");
	endKeyWord.push_back("to");
	
	daySeparator = ":-,/ ";
	hourSeparator = "h:";
	/*dayName = {"monday","tuesday","wednesday","thrusday","friday",
							"saturday","sunday",
							"mon","tue","wed","thu","fri","sat","sun"};
	vector<string> monthName={"january","february","march","april","may","june",
							"july","august","september","october","november","december",
							"jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"};
	*/
	currentTime = getCurrentTime();
	task = command;
	needList = &allTask->getUpcomingTasks();
}

AddProcess::AddProcess(Task task,TaskList *list):LogicProcess(task,list){
}

AddProcess::~AddProcess(){
}

Time AddProcess::getCurrentTime(){
	Time current;
	time_t t = time(0);   // get time now
    struct tm * now = localtime( & t );
	current.setYear(now->tm_year + 1900);
	current.setMon(now->tm_mon + 1);
	current.setDay(now->tm_mday);
	current.setHour(now->tm_hour);
	current.setMin(now->tm_min);

	return current;
}

string AddProcess::getLastWord(string& str){
	int size = str.size();
	int start = str.find_last_of(" ");
	string result;
	if (start!=-1){
		result = str.substr(start+1,size-start-1);
		str = str.substr(0,start);
	}
	else {
		result = str;
		str = "";
	}

	return result;
}

Task AddProcess::getFullTask(){
	return Task(task,startTime,endTime,false);
}

void AddProcess::solveContent(){
	endTime = lastTimePhrase();
	if (endTime.getYear() == 9999){
		startTime = currentTime;

		endTime.setMin(59);
		endTime.setHour(23);
		endTime.setDay(31);
		endTime.setMon(12);
		endTime.setYear(9999);
	}
	else{
		string lastWord = getLastWord(task);
		if (isEndKeyWord(lastWord)){
			startTime = lastTimePhrase();
			if (startTime.getYear()==9999)
				startTime=getCurrentTime();
			else{
				string startWord = getLastWord(task);
				if (!isStartKeyWord(startWord) && !isEndKeyWord(startWord))
					task+= " " + startWord;
			}
		}
		else if (isStartKeyWord(lastWord)){
			startTime = lastTimePhrase();
			string endWord = getLastWord(task);
			if (isEndKeyWord(endWord)){
				Time temp = startTime;
				startTime = endTime;
				endTime = temp;
			}
			else if (!isStartKeyWord(endWord))
				task+= " " + endWord;
		}
		else if (isDayPhrase(lastWord,startTime)){
		}
		else if (isHourPhrase(lastWord,startTime)){
		}
		else{
			startTime = currentTime;
			task+= " " + lastWord;
		}
	}
}

void AddProcess::HandleProcesss(){
	solveContent();
	Task newTask = getFullTask();
	//allTask->getUpcomingTasks().add(newTask);
	needList->add(newTask);

	//back up for undo
	backupToUndo(newTask);
	//To display list
	fromNeedtoDisplay();
}

void AddProcess::quickProcess(Task fullTask){
		needList->add(fullTask);
}

Time AddProcess::lastTimePhrase(){
	string lastWord;
	string penultiWord;
	Time result;

	lastWord = getLastWord(task);
	penultiWord = getLastWord(task);

	if (isDayPhrase(lastWord,result)){
		if (isHourPhrase(penultiWord,result));
		else {
			result.setHour(0);
			result.setMin(0);

			task+=" " + penultiWord;
		}
	}
	else if (isHourPhrase(lastWord,result)){
		if (isDayPhrase(penultiWord,result));
		else {
			result.setDay(currentTime.getDay());
			result.setMon(currentTime.getMon());
			result.setYear(currentTime.getYear());

			task+=" " + penultiWord;
		}
	}
	else {
		task+=" " + penultiWord + " " + lastWord;

		result.setMin(59);
		result.setHour(23);
		result.setDay(31);
		result.setMon(12);
		result.setYear(9999);
	}

	return result;
}

bool AddProcess::isDayPhrase(string str,Time& dayPhrase){
	int start=0;
	int end;
	int size = str.size();
	int result=0;
	
	end = str.find_first_of(daySeparator,start);
	if (end!=-1){
		string day = str.substr(start,end-start);
 		int d = isPositiveInteger(day);
		if (d>=0 && d <=31) {
			dayPhrase.setDay(d);
			result++;
		}
		start = end+1;
	}

	end = str.find_first_of(daySeparator,start);
	if (end!=-1){
		string month = str.substr(start,end-start);
		int m = isPositiveInteger(month);
		if (m>=1 && m<= 12) {
			dayPhrase.setMon(m);
			result++;
		}
		start = end+1;
	}

	end = size;
	string year = str.substr(start,end-start);
	int y = isPositiveInteger(year);
	if (y>=currentTime.getYear()) {
		dayPhrase.setYear(y);
		result++;
	}

	return (result==3);
}

bool AddProcess::isHourPhrase(string str,Time& hourPhrase){
	int start=0;
	int end;
	int size = str.size();
	int result=0;
	
	end = str.find_first_of(hourSeparator,start);
	string hour = str.substr(start,end-start);
	int h = isPositiveInteger(hour);
	if (h>=0 && h <=24) {
		hourPhrase.setHour(h);
		result++;
	}

	start = end+1;
	end = size;
	string min = str.substr(start,end-start);
	int m = isPositiveInteger(min);
	if (m>=0 && m<= 59) {
		hourPhrase.setMin(m);
		result++;
	}

	return (result==2);
}

bool AddProcess::isDaySeparator(char testChar){
	int size = daySeparator.size();
	for (int i=0;i<size;i++)
		if (testChar==daySeparator[i]) return true;

	return false;
}

bool AddProcess::isHourSeparator(char testChar){
	int size = hourSeparator.size();
	for (int i=0;i<size;i++)
		if (testChar==hourSeparator[i]) return true;

	return false;
}

bool AddProcess::isStartKeyWord(string word){
	int size = startKeyWord.size();
	for (int i=0;i<size;i++)
		if (word==startKeyWord[i]) return true;

	return false;
}

bool AddProcess::isEndKeyWord(string word){
	int size = endKeyWord.size();
	for (int i=0;i<size;i++)
		if (word==endKeyWord[i]) return true;

	return false;
}

/*bool Add::isDayName(string name){
	int size = dayName.size();
	for (int i=0;i<size;i++)
		if (name==dayName[i]) return true;

	return false;
}

bool Add::isMonthName(string name){
	int size = monthName.size();
	for (int i=0;i<size;i++)
		if (name==monthName[i]) return true;

	return false;
}
*/

void AddProcess::backupToUndo(Task task){
	taskContainer contain=upcoming;
	commandType type=Delete;
	pushToUndoList(task,type,contain,false);
}

//return the integer if str is an integer
//return -1 is not
int AddProcess::isPositiveInteger(string str){
	int result;
	char it = 0;
    while (it != str.length() && isdigit(str[it])) ++it;
    if (!str.empty() && it == str.length()){
		istringstream convert(str);
		convert >> result;
	}
	else result = -1;
	return result;
}

string AddProcess::getTask(){
	return task;
}

Time AddProcess::getStartTime(){
	return startTime;
}

Time AddProcess::getEndTime(){
	return endTime;
}

string AddProcess::toString(){
	ostringstream output;
	output << task << "\n"
		<< startTime.getMin() << " - "
		<< startTime.getHour() << " - "
		<< startTime.getDay() << " - "
		<< startTime.getMon() << " - "
		<< startTime.getYear() << "\n"
		<< endTime.getMin() << " - "
		<< endTime.getHour() << " - "
		<< endTime.getDay() << " - "
		<< endTime.getMon() << " - "
		<< endTime.getYear() << endl;

	return output.str();
}
